﻿using System;
using System.Globalization;
using System.IO;
using System.Windows.Media.Imaging;
using BitMiracle.LibTiff.Classic;
using FirstFloor.Documents.Imaging;
using FirstFloor.Documents;

namespace FirstFloor.Documents.IO.LibTiff
{
    /// <summary>
    /// Implements a TIFF decoder for Document Toolkit.
    /// </summary>
    /// <remarks>
    /// By default Document Toolkit does not support TIFF images embedded in XPS documents. Register this decoder to add support for TIFF images. Register
    /// by invoking ImageDecoders.RegisterImageDecoder(ContentType.TypeImageTiff, new TiffDecoder());
    /// </remarks>
    public class TiffDecoder
        : IImageDecoder
    {
        /// <summary>
        /// Decodes the image from specified stream.
        /// </summary>
        /// <param name="stream">The stream.</param>
        /// <param name="frame">The image frame if the image format supports multiple image frames.</param>
        /// <returns>The decoded bitmap source</returns>
        public BitmapSource Decode(Stream stream, short frame)
        {
            if (stream == null) {
                throw new ArgumentNullException("stream");
            }
            if (frame < 0) {
                throw new ArgumentOutOfRangeException("frame");
            }
            var image = Tiff.ClientOpen("tiff", "r", stream, new TiffStream());
            if (image == null) {
                throw new ArgumentException("Stream does not contain a valid TIFF image");
            }

            try {
                image.SetDirectory(frame);

                var frameSize = image.GetFrameSize();
                var width = (int)frameSize.Width;
                var height = (int)frameSize.Height;
                var pixels = new int[width * height];

                image.ReadRGBAImage(width, height, pixels);

                var bitmap = new WriteableBitmap(width, height);
                for (int y = 0; y < height; y++) {
                    var ytif = y * width;
                    var ybmp = (height - y - 1) * width;

                    for (int x = 0; x < width; x++) {
                        var currentValue = pixels[ytif + x];

                        // Shift the Tiff's RGBA format to the Silverlight WriteableBitmap's ARGB format
                        bitmap.Pixels[ybmp + x] = Tiff.GetB(currentValue) | Tiff.GetG(currentValue) << 8 | Tiff.GetR(currentValue) << 16 | Tiff.GetA(currentValue) << 24;
                    }
                }

                return bitmap;
            }
            finally {
                image.Dispose();
            }
        }
    }
}
